`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2021/05/12 19:18:06
// Design Name: 
// Module Name: Ifetc32
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////

module Ifetc32(
    input [31:0] Addr_result,    //address conputed
    input [31:0] Read_data_1,   // 
    input Branch,
    input nBranch,
    input Jmp,       //j
    input Jal,
    input Jr,
    input Zero,
    input clock,
    input reset,
    output [31:0] Instruction,
    output [31:0] branch_base_addr,  // (pc+4) to ALU used by branch type instruction
    output [31:0] link_addr, // (pc+4) to decoder which is used by jal instruction
    output [31:0] pco
    );
    reg [31:0] link_addr_reg;
    assign link_addr = link_addr_reg;
    
    
    reg [31:0] PC;
    assign pco = PC;
    
    
    prgrom instmem(
        .clka(clock),       //input wire
        .addra(PC[15:2]),   //input wire
        .douta(Instruction) //output wire
    );
    
    reg [31:0] Next_PC;
    wire [31:0] PCplus4;
    assign PCplus4[31:0] = PC + 32'd4;
    assign branch_base_addr = PCplus4;
    
    
    always@(*) begin
        if(Jr) begin
            Next_PC = Read_data_1<<2;
        end
        else if(Branch == 1 && Zero == 1 || nBranch == 1 && Zero == 0) begin
            Next_PC = Addr_result<<2;
        end
        else begin
            Next_PC = PCplus4;
        end
    end
   
    //j, jal and reset
    always @(negedge clock) begin
        if(reset) begin
            PC <= 32'h00000000;
        end
        else if(Jal) begin
            
            PC <= {4'b0000, Instruction[25:0], 2'b00};
        end
        else if(Jmp) begin
       
            PC <= {4'b0000, Instruction[25:0], 2'b00};
        end
       
        else begin
            PC <= Next_PC;
            //PC = nextPC;
        end
    end
    
    always @(posedge Jal, posedge Jmp) begin
        link_addr_reg <= branch_base_addr>>2;
    end
    
endmodule
